#ifndef  PILO_MEMORYALLOCATORS_H
#define  PILO_MEMORYALLOCATORS_H

#include "common/common.h"
#include "memory/memory.h"
#include "memory/pilomemoryrecordedblock.h"


namespace PILO 
{ 
    namespace Core 
    {
        namespace Memory 
        {
            class PILOIMemoryAllocator 
            {
            public:
                virtual ~PILOIMemoryAllocator() {;};

                virtual void* alloc(size_t size) = 0;
                virtual BOOL free(void* p) =0;
                virtual size_t unitSize() const = 0;
            virtual void clear() = 0;

            private:

            };


            /**
            * use standard memory management function malloc, calloc, free,and realloc
            */
            class PILOHeapAllocator : public PILOIMemoryAllocator
            {
            public:
                PILOHeapAllocator()
                {
                }
                ~PILOHeapAllocator()
                {
                }
                void* alloc(size_t size) 
                {
                    return MemoryAlloc(size);
                    //return (operator new (size));
                }
                BOOL free(void* p)
                {
                    if (p != static_cast<void *>(0)) {
                        MemoryFree(p);
                        p = (void *) 0;
                    }
                    return TRUE;
                }
                size_t unitSize() const
                {
                    return 0;
                }
                void clear()
                {
                    return;
                }
            };

            /**
            * alloc memory from a big trunk of memeory block 
            */
            template <typename T, int capacity> class PILOTBlockAllocator : public PILOIMemoryAllocator
            {
            public:
                PILOTBlockAllocator()
                {
                    m_rs.Initialize(sizeof(T), capacity);
                }
                ~PILOTBlockAllocator()
                {
                }
                void* alloc(size_t /*size*/) 
                {
                    HANDLE h = m_rs.AllocRecord();
                    if(!h) return NULL;
                    return m_rs.GetRecordData(h);
                }
                BOOL free(void* p)
                {
                    HANDLE h = m_rs.GetHandle(p);
                    return m_rs.FreeRecord(h);
                }
                size_t unitSize() const
                {
                    return (sizeof(T)+3)&(~(int)3);
                }
                void clear()
                {
                    m_rs.Clear();
                }

            public:
                PILOMemoryRecordedBlock m_rs;
            };
        }
    }   
}


#endif /* PILO_MEMORYALLOCATORS_H */

